package com.spdzen.service.impl;

import java.util.LinkedList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.spdzen.mapper.SysResourceMapper;
import com.spdzen.model.SysResource;
import com.spdzen.model.SysUser;
import com.spdzen.service.SysResourceService;
import com.spdzen.service.SysRoleResourceService;
import com.spdzen.service.SysUserService;
import com.spdzen.support.SimpleServiceImpl;
import com.spdzen.support.SimpleTreeNode;
import com.spdzen.support.constant.DbConstants;
import com.spdzen.support.exception.ResultCodeException;
import com.spdzen.support.result.BizResultCode;
import com.spdzen.support.shiro.ShiroDynamicAuthorization;
import com.spdzen.vo.SysResourceAdminVO;
import com.spdzen.vo.search.SysResourceAdminSearch;

/**
 * 后台管理系统功能（URL区别） 服务实现类
 */
@Service("sysResourceService")
public class SysResourceServiceImpl extends SimpleServiceImpl<SysResourceMapper, SysResource> implements SysResourceService {
	@Resource
	private SysRoleResourceService sysRoleResourceService;

	@Resource
	private SysUserService sysUserService;
	
	@Override
	public List<SysResource> selectChildrenByUser(Long sysUserId, Long parentId, boolean onlyMenu) {
		SysUser user = sysUserService.selectById(sysUserId);
		if (user == null) {
			return new LinkedList<>();
		}
		
		List<SysResource> rows = null;
		
		int userType = user.getType().intValue();
		if (userType == DbConstants.SYS_USER_TYPE_NORMAL) {
			// 普通用户
			rows = baseMapper.selectChildrenByUser(sysUserId, parentId);
		} else if (userType == DbConstants.SYS_USER_TYPE_SUPER) {
			// 超级用户
			rows = baseMapper.selectChildren(parentId);
		}
		
		List<SysResource> tmp = new LinkedList<>();
		if(onlyMenu){
			for(SysResource row : rows) {
				if(row.getType().intValue() != DbConstants.SYS_RESOURCE_TYPE_BUTTON){
					tmp.add(row);
				}
			}
			
			rows = tmp;
		}
		
		return rows;
	}
	
	@Override
	public List<SysResource> selectTopMenus(Long sysUserId) {
		return selectChildrenByUser(sysUserId, 0L, true);
	}
	
	@Override
	public List<SimpleTreeNode<SysResource>> selectSubTreeByUser(Long sysUserId, Long parentId, boolean onlyMenu) {
		SysUser user = sysUserService.selectById(sysUserId);
		if (user == null) {
			return new LinkedList<SimpleTreeNode<SysResource>>();
		}

		List<SysResource> rows = null;
		int userType = user.getType().intValue();
		if (userType == DbConstants.SYS_USER_TYPE_NORMAL) {
			// 普通用户
			rows = baseMapper.selectChildrenByUser(sysUserId, null);
		} else if (userType == DbConstants.SYS_USER_TYPE_SUPER) {
			// 超级用户
			rows = baseMapper.selectChildren(null);
		}
		
		List<SimpleTreeNode<SysResource>> nodes = new LinkedList<>();
		if(rows == null || rows.isEmpty()) {
			return nodes;
		}
		
		SimpleTreeNode<SysResource> parentNode = null;
		for(SysResource row : rows) {
			if(onlyMenu && row.getType().intValue() == DbConstants.SYS_RESOURCE_TYPE_BUTTON){
				// 如果是按钮，不显示
				continue;
			}
			
			SimpleTreeNode<SysResource> node = new SimpleTreeNode<>();
			node.setId(row.getId().toString());
			node.setName(row.getName());
			node.setNodeData(row);
			node.setParentId(row.getParentId().toString());
			
			nodes.add(node);
			
			if(parentId != null && parentId.longValue() == row.getId().longValue()){
				parentNode = node;
			}
		}
		
		SimpleTreeNode.buildTree(nodes);
		
		List<SimpleTreeNode<SysResource>> c = null;
		if(parentNode != null){
			c = parentNode.getChildren();
		}
		
		return c;
	}

	@Override
	public List<SimpleTreeNode<SysResource>> selectMenuTreeByUser(Long sysUserId) {
		return selectSubTreeByUser(sysUserId, null, true);
	}

	@Override
	@Transactional(rollbackFor = { Exception.class })
	@ShiroDynamicAuthorization
	public void insertIfPermission(SysResource entity) throws Exception {
		insert(entity);

		SysResource sr = new SysResource();
		sr.setCode(entity.getCode());
		if (selectCount(sr) > 1) {
			throw new ResultCodeException(BizResultCode.error("菜单编号已经存在！"));
		}
	}

	@Override
	@Transactional(rollbackFor = { Exception.class })
	@ShiroDynamicAuthorization
	public void updateIfPermission(SysResource entity) throws Exception {
		SysResource record = baseMapper.selectById(entity.getId());

		if (record == null) {
			throw new ResultCodeException("菜单不存在！");
		}

		Integer category = record.getCategory();
		if (category == null || category.intValue() != 1) {
			throw new ResultCodeException("菜单不允许编辑！");
		}

		updateById(entity);
		SysResource sr = new SysResource();
		sr.setCode(entity.getCode());
		if (selectCount(sr) > 1) {
			throw new ResultCodeException(BizResultCode.error("菜单编号已经存在！"));
		}
	}

	@Override
	public boolean isCodeExists(String code) {
		if (StringUtils.isBlank(code)) {
			return false;
		}

		code = code.trim();

		SysResource entity = new SysResource();
		entity.setCode(code);

		return selectCount(entity) > 0;
	}

	@Override
	public List<SysResource> selectAllForTree() {
		Wrapper<SysResource> wrapper = new EntityWrapper<>();
		wrapper.orderBy("parent_id,sort");
		return baseMapper.selectList(wrapper);
	}

	@Override
	@Transactional(rollbackFor = { Exception.class })
	@ShiroDynamicAuthorization
	public void deleteIfPermission(Long id) throws Exception {
		SysResource record = baseMapper.selectById(id);

		if (record == null) {
			throw new ResultCodeException("菜单不存在！");
		}

		Integer category = record.getCategory();
		if (category == null || category.intValue() != 1) {
			throw new ResultCodeException("菜单不能删除！");
		}

		record = new SysResource();
		record.setParentId(id);
		Wrapper<SysResource> wrapper = new EntityWrapper<>(record);

		if (baseMapper.selectCount(wrapper) > 0) {
			throw new ResultCodeException("菜单下面有子菜单，不能删除！");
		}

		sysRoleResourceService.deleteByResource(id);
		baseMapper.deleteById(id);
	}

	@Override
	public List<SysResourceAdminVO> selectAllAdminVOForTree() {
		SysResourceAdminSearch search = new SysResourceAdminSearch();
		return baseMapper.selectAdminVO(search);
	}

	@Override
	public SysResourceAdminVO selectOneAdminVO(Long id) {
		return baseMapper.selectOneAdminVO(id);
	}
}
